<?php
/**
 * 字符串操作类,直接进行调用
 */

class str{

	/**
	 * 可以处理中文的substr函数,中文占两个字符处理
	 *
	 * @param string $str 字符串
	 * @param integer $from 起始截取值
	 * @param integer $len 长度值
	 * @return string 截取后的文字
	 */
	function substring($str,$from,$len){
		preg_match_all('#(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+)#s',$str,$array, PREG_PATTERN_ORDER);

		$from1=0;$len1=0;
		$s='';
		foreach($array[0] as $key => $val){
			$n=ord($val)>=128 ? 2:1;
			$from1+=$n;
			if($from1>$from){
				$len1+=$n;
				if($len1<=$len){
					$s.=$val;
				}else{
					return $s.'..';
				}
			}
		}
		return $s;
	}

	/**
	 * 分页列表
	 *
	 * @param string $url 路径模板
	 * @param integer $rows 记录总数
	 * @param integer $pid 当前页
	 * @param integer $rn 每页显示数
	 * @param string $inner 模板
	 * @return string 分页代码
	 */
	function pagelist($url='',$rows=0,$pid=1,$rn=20,$inner=null){
//exit($url);
		$lnk="<a href=\"%s\">%s</a>";

		$pcount=($rows/$rn); //总页数 可能非int类型，所以做如下比较并赋值

		if($rows==0||$pcount==1) return '';//不要返回false
		if($pid==null) $pid=1;
		if($pcount!=(int)$pcount) $pcount=(int)$pcount+1;
		//如果当前页大于总页数，这个是不现实的..
		if($pid>$pcount) $pid=$pcount;

		$url=str_replace('RN',$rn,$url);
		$inner=isset($inner{0}) ? $inner : '<p class="k_pagelist">{Standard/}{Next/}</p>';

		//Next
		$next=($pid==$pcount)
			? '<span>Next &gt;</span>'
			: sprintf($lnk,str::formatPath($url,$pid+1),'Next &gt;');//'<a href="'.str::formatPath($url,$pid+1).'">Next &gt;</a>';

		//Previous
		$previous=$pid==1
			? '<span>&lt; Previous</span>'
			: sprintf($lnk,str::formatPath($url,$pid-1),'&lt; Previous');//'<a href="'.str::formatPath($url,$pid-1).'">&lt; Previous</a>';

		//Standard
		$numr=5;							//每页右侧显示翻页数量
		$numl=2;						 //左侧显示2个
		$num=$numr+$numl+1;	 //合计显示

		$sta= $pid==1 ? '<strong>1</strong>' : sprintf($lnk,str::formatPath($url,1),1);//'<a href="'.str::formatPath($url,1).'">1</a>';//Page 1

		if($pcount>=2){	 //Page 2
			$sta.= $pid==2 ? '<strong>2</strong>' : sprintf($lnk,str::formatPath($url,2),2);//'<a href="'.str::formatPath($url,2).'">2</a>';
		}

		if($pid>=$numl+4 && $pcount>$num+3)
			$sta.='<i>...</i>';

		$i_sta=$pid-$numl;		//开始
		$i_end=$pid+$numr;		//结束

		if($pid<=$numl+2){		 //重新设置结束
			$i_end=$num+2;
		}

		if($pid>=$pcount-$num+2){ //重新设置开始
			$i_sta=$pcount-$num;
		}
		for($i=$i_sta;$i<$i_end;$i++){	//循环
			if($i>=3 && $i<=$pcount-2){
				$i==$pid
					? $sta.='<strong>'.$i.'</strong>'
					: $sta.=sprintf($lnk,str::formatPath($url,$i),$i);//'<a href="'.str::formatPath($url,$i).'">'.$i.'</a>';
			}
		}

		if($pid+$numr<=$pcount-2 && $pcount-2>$num+1)
			$sta.='<i>...</i>';

		if($pcount>3){
			$pid==$pcount-1			//Page Count-1
				? $sta.='<strong>'.($pcount-1).'</strong>'
				: $sta.=sprintf($lnk,str::formatPath($url,$pcount-1),$pcount-1);//'<a href="'.str::formatPath($url,$_count-1).'">'.($_count-1).'</a>';
		}

		if($pid==$pcount){	 //Page Count
			if($pcount>=3)
				$sta.='<strong>'.$pcount.'</strong>';
		}else{
			if($pcount>=3)
				$sta.=sprintf($lnk,str::formatPath($url,$pcount),$pcount);//'<a href="'.str::formatPath($url,$pcount).'">'.$pcount.'</a>';
		}
		//first
		$pid==1
			? $first='<strong>&lt;&lt; First</strong>'
			: $first=sprintf($lnk,str::formatPath($url,1),'&lt;&lt; First');//'<a href="'.str::formatPath($url,1).'">&lt;&lt; First</a>';

		//last
		$pid==$pcount
			? $last='<strong>Last &gt;&gt;</strong>'
			: $last=sprintf($lnk,str::formatPath($url,$pcount),'Last &gt;&gt;');//'<a href="'.str::formatPath($url,$pcount).'">Last &gt;&gt;</a>';

		//jump
		$jump='<input type="text" size="3" onkeydown="if(event.keyCode==13) {window.location=\''.str::formatPath($url,"'+this.value+'").'\'; return false;}" />';//sprintf(str_replace('pid=PID','pid=%s',$_url),"'+this.value+'",$_rn)

		$assign=array(
			'standard'=>$sta,
			'priveious'=>$previous,
			'next'=>$next,
			'first'=>$first,
			'last'=>$last,
			'jump'=>$jump,
			'pagecount'=>$pcount,
			'count'=>$rows,
			'pid'=>$pid,
			'rn'=>$rn,
		);

		$tmp=new template;
		$tmp->assign=$assign;
		$tmp->load_string=$inner;
		return $tmp->output();
	}

	/**
	 * 格式化路径
	 *
	 * 对文件名进行判断，自动补充物理生成的路径或链接路径并返回
	 *
	 * @param string $path 路径或文件名
	 * @param integer $pid 第X页
	 * @param integer $is 默认0输出链接;1输出文件生成地址(这个输出链接为相对根路径)
		$is 判断并不是对其路径进行补充处理，也就是说不在前面补充PATH或ROOT路径
	 * @return string 格式化后的路径
	 */
	function formatPath($path,$pid=1,$is=0){
		if(empty($path)) return false;

		$pidline='-';
		$filepath='index.htm';

		if(strpos($path,'PID')===false){//若不包含PID，则根据需要进行补充
			if(substr($path,-1,1)=='/'){//目录结构
				if($pid=='1'){
					$path= $is ? $path.$filepath : $path;
				}else{
					$path=substr($path,0,strlen($path)-1).$pidline.$pid.'/'.($is ? $filepath : '');
				}
			}else{//文件结构
				$ext=strrchr($path,'.');
				$fname=substr($path,0,strlen($path)-strlen($ext));
				if($pid==1){
					//$path=$fname.$ext;
				}else{
					$path=$fname.$pidline.$pid.$ext;
				}
			}

		}else{//有PID
			/*
			$path=str_replace('PID',$pid==1 ? '' : $pid , $path);
			if (strpos($path,'?')===false) {//静态或伪静态
				$path=str_replace($pidline.'PID',($pid==1 ? '' : $pidline.$pid) , $path);
			}else{
				$path=str_replace('PID',$pid==1 ? '' : $pid , $path);
			}
			 */
			$path=str_replace('PID',$pid,$path);
			if($is && substr($path,-1,1)=='/'){//输出生成地址
				$path.=$filepath;
			}
		}
		return $path;
	}

	function formatSize($num) {
		if($num==0) return '-';
		$_array=array('byte', 'KB', 'MB', 'GB', 'TB', 'PB');
		$i=0;
		while ($num >= 1024) {
			$num /= 1024;
			$i++;
		}
		return number_format($num,($i==0 ? 0 :2)).' '.$_array[$i];
	}

	/**
	 * 格式化伪正则为正则表达式
	 * @param string $s 字符串
	 */
	function formatPreg($s){
		$s=preg_quote($s);
		$find=array(
			'\[d\]'=>'\d',
			'\[D\]'=>'\D',
			'\[w\]'=>'[a-zA-Z0-9]',
			'\[W\]'=>'\W',
			'\[S\]'=>'\S',
			'\[s\]'=>'\s',
			'\[\.\]'=>'.',
			'\{\?\}'=>'?',
			'\{\+\}'=>'+',
			'\{\*\}'=>'*',
			'\{\$\}'=>'$',
			'\{\^\}'=>'^',
			'\<\<'=>'(',
			'\>\>'=>')',
		);
		$s=str_replace(array_keys($find),$find,$s);
		$s=preg_replace('/\\\{(\d+)(,\d+)?\\\}/','{$1$2}',$s);//{3}/{1,3}类型格式化
		//$s=preg_replace('/\\\(([^)]+)\\\)/s','$2',$s);
		return '%'.$s.'%s';
	}
	/**
	 * 把链接地址格式化为完整的路径形式
	 * @param string $url 参考完整路径
	 * @param string $href 链接地址
	 */
	function formatUrl($url,$href){
		$new='';
		if (kc_validate($href,6)) {
			$new=$href;

		}elseif(substr($href,0,1)=='/'){
			preg_match('/^([a-zA-Z]{3,10}:\/\/[^\/]*)/',$url,$out);
			$new=$out[0].$href;
		}elseif(substr($href,0,3)=='../'){
			preg_match('/^((\.\.\/)+)(.*)$/',$href,$out);
			$n=strlen($out[1])/3;
			$u=$url;
			for ($i = 0 ; $i <= $n ; $i++) {
				$u=dirname($u);
			}
			$new=$u.'/'.$out[3];
		}elseif(substr($href,0,2)=='./'){
			$new=dirname($url).'/'.basename($href);
		}elseif(strtolower(substr($href,0,7))=='mailto:' || strtolower(substr($href,0,11))=='javascript:'){
			return false;
		}else{
			$new=dirname($url).'/'.$href;
		}
		return kc_validate($new,6) ? $new : false;
	}
	/**
	 * 获得随机数
	 *
	 * @param integer $length 返回的随机值的长度
	 * @param integer $type 返回的随机值的类型 1:数字 2:小写英语 3:大写英语 4:字母和字符 默认为数字和小写英文
	 *	 	1: 数字
	 * 		2: 小写字母
	 * 		3: 大些字母
	 * 		default: 数字和小写字符
	 * @return string 随机字符

	*/
	function random($length,$type=0){
			switch($type){
			case 1:$pattern="1234567890";break;
			case 2:$pattern="abcdefghijklmnopqrstuvwxyz";break;
			case 3:$pattern="ABCDEFGHIJKLMNOPQRSTUVWXYZ";break;
			case 4:$pattern="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890~!@#$%^&*()_-+=";break;
			default:$pattern="1234567890abcdefghijklmnopqrstuvwxyz";
		}
		$size=strlen($pattern)-1;
		$key=$pattern{rand(0,$size)};
		for($i=1;$i<$length;$i++)
		{
			$key.= $pattern{rand(0,$size)};
		}
		return $key;
	}

	function getTime(){
		$mt=explode(' ',microtime());
		return $mt[0]+$mt[1];
	}

	/**
	 * 返回数值形式的IP地址
	 *
	 * @return integer IP地址
	 */
	function ip(){
		if (!empty($_SERVER['HTTP_CLIENT_IP'])){   //check ip from share internet
			$ip=$_SERVER['HTTP_CLIENT_IP'];
		}elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){   //to check ip is pass from proxy
			$ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
		}else{
			$ip=$_SERVER['REMOTE_ADDR'];
		}
		if(!kc_validate($ip,11)){$ip='127.0.0.1';};
		return str::ipToLong($ip);
	}

	function formatIp($address){
		$pattrn='/(\d{1,3}\.\d{1,3})\.[0-9\.]+/';
		return preg_replace($pattrn,'$1.*.*',$address);
	}

	function getIp($ip){
		$db =  new db;
		$rs=$db->getRows_one('%s_ip','country,address,province,city,area',"ipstart>$ip and ipend <$ip");
		if (!empty($rs)) {
			return $rs['country'].$rs['address'].$rs['province'].$rs['city'].$rs['area'];
		}
	}

	function ipToLong($ip){
		return bindec(decbin(ip2long($ip)));
	}

	/**
	 * 格式化时间戳为标准日期，并设置时差
	 *
	 * @param integer $time 时间戳
	 * @param string $mode 输出格式
	 * @param integer $isstr 默认直接输出，若是设置为1，输出字符串形式
	 * @return string 日期
	 */
	function formatDate($time,$mode='Y-m-d',$isstr=0){

		if ($time==0) return '--';

		//计算时差
		$time1 = $time + (TIMEDIFF * 3600);

		if($isstr){//字符串形式输出
			$ftime=gmdate('Ymd',$time);
			if($ftime==gmdate('Ymd',time())){
				$s=kc_lang('time.today').gmdate('(H:i)',$time1);
			}elseif($ftime==gmdate('Ymd',time()-86400)){
				$s=kc_lang('time.yester').gmdate('(H:i)',$time1);
			}else{
				$s=gmdate($mode,$time1);
			}
		}else{
			$s=gmdate($mode,$time1);
		}

		return $s;
	}

	/**
	 * 转义字符串为正则可用的表达式
	 *
	 * 替换*和?为正则可用的
	 * 
	 * @param string $str 要转义的字符串
	 * @param bool $is 默认0:只替换*?, 1:闭合,补充开始和结尾表达式
	 */
	function pregQuote($str,$is=0){
		$str=$is ? '/^'.preg_quote($str).'$/s' : '/'.preg_quote($str).'/';
		$str=str_replace('\*','.*',$str);
		$pre=str_replace('\?','.?',$str);
		return $pre;
	}


	/**
	 * 字符或数字转换为路径
	 * 
	 * @param string|integer $str 字符或数字
	 * @return string 带/的路径格式
	 */
	function toPath($str){
		
		//左侧用0填充到10个字符
		$path=str_pad((string)$str, 10, '0',STR_PAD_LEFT);
		
		//按2个2个作为数组
		$array=str_split($path,2);

		//数组转换为字符串，并以/拆分
		return implode('/',$array);

	}
	/**
	 * 返回文字长度,中文占两个字符
	 *
	 * @param string $str 要计算长度的文字段
	 * @return integer 长度值
	 */
	function len($str){
		preg_match_all ('#(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+)#s',$str,$array, PREG_PATTERN_ORDER);
		$len=0;
		foreach($array[0] as $val){
			$len+=ord($val)>=128 ?2:1;
		}
		return $len;
	}

}




?>